/*
 * Created on 14/08/2005
 *
 */
package guru.mercurio.core.delivery;

import guru.mercurio.common.AbsoluteApplicationAddress;
import guru.mercurio.common.RelativeApplicationAddress;
import guru.mercurio.data.ChannelDataManager;
import guru.mercurio.data.DataManager;
import guru.merlin.core.CantHandException;
import guru.merlin.core.Envelope;
import guru.merlin.core.EnvelopeCantHandException;
import guru.merlin.core.InfrastructureCantHandException;
import guru.merlin.core.RuntimeConfigurationCantHandException;

import java.util.HashSet;
import java.util.Set;

import org.apache.log4j.Logger;


public class PreDispatchProcessor {
    Logger logger=Logger.getLogger (PreDispatchProcessor.class);
    Set multiplexedChannels;
    DataManager dm;
    ChannelDataManager cdm;
    
    public PreDispatchProcessor (DataManager dm) throws Exception{
        this.dm=dm;
        cdm=new ChannelDataManager (dm);
        multiplexedChannels=loadMultiplexedChannels ();
        
    }
    
    private Set loadMultiplexedChannels () {
        Set map = new HashSet ();
        map.add ("22625");
        return (map);
    }
    
    public AbsoluteApplicationAddress preProcess (Envelope envelope) throws CantHandException {
        //String msg = "";
        String text;
        String word;
        String rest;
        int pos;
        AbsoluteApplicationAddress[] apps;
        AbsoluteApplicationAddress app = null;
        
        
        if(!(envelope.getDestination () instanceof RelativeApplicationAddress)){
            throw new EnvelopeCantHandException ("Can't preprocess an Envelope with a destination different from ApplicationAddress");
        }
        
        String channelId=envelope.getDestination ().getPort ();
        if (multiplexedChannels.contains (channelId)) {
            logger.debug ("Es un canal multiplexado");
            if ((pos = (text = envelope.getContent ().toString ()).indexOf (" ")) != -1) {
                word = text.substring (0, pos);
                rest = text.substring (pos);
            } else {
                word = text;
                rest = "";
            }
            try {
                apps = cdm.getApplicationBySubChannel (channelId, word);
                if (apps!=null && apps.length == 1) {
                    logger.info ("Se encontr una aplicacin para subcanal '" + word + "@" + channelId + "'");
                    app = apps[0];
                    envelope.setContent (rest.trim ());
                    return app;
                } else if (apps!=null && apps.length == 0) {
                    logger.info ("No se encontr una aplicacin para subcanal '" + word + "@" + channelId + "', intentando bsqueda de app default para canal multiplexado '" + channelId + "'");
                    try{
                        apps = cdm.getApplicationByChannel (channelId);
                    } catch(Exception e){
                        throw new InfrastructureCantHandException (""+e);
                    }
                    
                    if (apps.length == 1) {
                        logger.info ("Se encontr app default para canal multiplexado '" + channelId + "'");
                        app = apps[0];
                        //envelope.setMetaDestination(app);
                        return app;
                    } else {
                        throw new RuntimeConfigurationCantHandException ("No se encontr app default para canal multiplexado '" + channelId + "'");
                    }
                } else {
                    throw new RuntimeConfigurationCantHandException ("Se encontaron muchas aplicaciones para un mismo subcanal: no se cul utilizar.");
                }
            }catch (Exception e2) {
                logger.debug ("Es un canal NO multiplexado");
                try{
                    apps = cdm.getApplicationByChannel (channelId);
                } catch(Exception e){
                    throw new InfrastructureCantHandException (""+e);
                }
                if (apps.length == 1) {
                    logger.info ("Se encontro una aplicacion para canal '" + channelId + "', del pasaporte '" + apps[0].getPassport () + "'");
                    app = apps[0];
                    //envelope.setMetaDestination(app);
                    return app;
                } else {
                    throw new RuntimeConfigurationCantHandException ("No se encontro una aplicacion para canal '" + channelId + "'");
                }
            }
        } else {
            logger.debug ("Es un canal NO multiplexado");
            try{
                apps = cdm.getApplicationByChannel (channelId);
            } catch(Exception e){
                throw new InfrastructureCantHandException (""+e);
            }
            if (apps.length == 1) {
                logger.info ("Se encontro una aplicacion para canal '" + channelId + "', del pasaporte '" + apps[0].getPassport () + "'");
                app = apps[0];
                //envelope.setMetaDestination(app);
                return app;
            } else {
                throw new RuntimeConfigurationCantHandException ("No se encontro una aplicacion para canal '" + channelId + "'");
            }
        }
        //return null;
    }
}